﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Web;
using BolsaWeb.Persistencia;
using BolsaWeb.Dominio;
using NHibernate.Criterion;
namespace BolsaWeb.Negocio
{
    public class BolsaTrabajoService
    {
        IPostulanteDAO PostulanteDAO { get; set; }
        IAvisoDAO AvisoDAO { get; set; }
        IOfertanteDAO OfertanteDAO { get; set; }
        IUsuarioDAO UsuarioDAO { get; set; }
        IAvisoPostulanteDAO AvisoPostulanteDAO { get; set; }
        public ICollection<Ofertante> listarOfertantes()
        {
            return OfertanteDAO.ListarTodos();
        }
        public Ofertante obtenerOfertante(Int32 id)
        {
            return OfertanteDAO.Obtener(id);
        }
        public Ofertante crearOfertante(String ruc, String rSocial, String correo, String clave)
        {
            if (String.Empty.Equals(ruc))
                throw new RucInvalidoException("El Ruc es obligatorio");
            if (ruc.Length != 11)
                throw new RucInvalidoException("El Ruc debe tener 11 dígitos");
            if (String.Empty.Equals(rSocial))
                throw new RazonSocialInvalidoException("Debe ingresar el nombre de Razon social");
            if (correo.IndexOf("@") == 0)
                throw new CorreoInvalidoException("Debe ingresar un correo válido");
            Ofertante to_o = new Ofertante();
            to_o.NumeroRuc = ruc;
            to_o.RazonSocial = rSocial;
            to_o.Correo = correo;
            to_o.Clave = clave;
            OfertanteDAO.Crear(to_o);
            Usuario user = new Usuario();
            user.Clave = to_o.Clave;
            user.Correo = to_o.Correo;
            user.Id = to_o.id;
            user.Tipo = Usuario.OFERTANTE;
            UsuarioDAO.Crear(user);
            return to_o;
        }
        public Aviso crearAviso(string titulo, string puesto, int idOfertante, DateTime fecIni, DateTime fecFin)
        {
            if (String.Empty.Equals(titulo))
                throw new Exception("Aviso invalido");
            Ofertante of = OfertanteDAO.Obtener(idOfertante);
            if (of == null)
                throw new Exception("Error aviso");
            Aviso aviso = new Aviso();
            aviso.Titulo = titulo;
            aviso.Puesto = puesto;
            aviso.FechaInicio = fecIni;
            aviso.FechaTermino = fecFin;
            aviso.Ofertante = of;
            AvisoDAO.Crear(aviso);
            return aviso;
        }
        public ICollection<Aviso> listarAvisos()
        {
            return AvisoDAO.ListarTodos();
        }
        public Aviso obtenerAviso(Int32 id)
        {
            return AvisoDAO.Obtener(id);
        }

        public ICollection<Postulante> listarPostulantes()
        {
            return PostulanteDAO.ListarTodos();
        }
        public ICollection<AvisoPostulante> listarPostulantes(int idAviso)
        {
            Aviso avisoExistente = AvisoDAO.Obtener(idAviso);
            DetachedCriteria busqueda = DetachedCriteria.For<AvisoPostulante>();
            busqueda.Add(Restrictions.Eq("Aviso", avisoExistente));
            return AvisoPostulanteDAO.Listar(busqueda);
        }
        public Postulante obtenerPostulante(Int32 id)
        {
            return PostulanteDAO.Obtener(id);
        }
        public Postulante crearPostulante(Postulante po)
        {
            if (po.Correo.IndexOf("@") == 0)
                throw new CorreoInvalidoException("Debe ingresar un correo válido");
            PostulanteDAO.Crear(po);
            Usuario user = new Usuario();
            user.Clave = po.Clave;
            user.Correo = po.Correo;
            user.Id = po.Id;
            user.Tipo = Usuario.POSTULANTE;
            UsuarioDAO.Crear(user);
            return po;
        }
        public Postulante modificarPostulante(Postulante po)
        {
            if (po.Correo.IndexOf("@") == 0)
                throw new CorreoInvalidoException("Debe ingresar un correo válido");
            PostulanteDAO.Modificar(po);
            Usuario user = new Usuario();
            user.Clave = po.Clave;
            user.Correo = po.Correo;
            user.Id = po.Id;
            user.Tipo = Usuario.POSTULANTE;
            UsuarioDAO.Modificar(user);
            return po;
        }
        public Ofertante modificarOfertante(Ofertante of)
        {
            if (of.Correo.IndexOf("@") == 0)
                throw new CorreoInvalidoException("Debe ingresar un correo válido");
            OfertanteDAO.Modificar(of);
            Usuario user = new Usuario();
            user.Clave = of.Clave;
            user.Correo = of.Correo;
            user.Id = of.id;
            user.Tipo = Usuario.OFERTANTE;
            UsuarioDAO.Modificar(user);
            return of;
        }
        public AvisoPostulante PostularAlAviso(Int32 IdPostulante, Int32 IdAviso)
        {
            // Validación de código de postulante no nulo ni vacío
            if (0 == IdPostulante)
                throw new Exception("El código de postulante no puede ser nulo o vacío");
            // Validación de postulante existente
            Postulante postulanteExistente = PostulanteDAO.Obtener(IdPostulante);
            if (null == postulanteExistente)
                throw new PostulanteInexistenteException("El postulante indicado no existe");
            // Validación de aviso existente
            Aviso avisoExistente = AvisoDAO.Obtener(IdAviso);
            if (null == avisoExistente)
                throw new AvisoInexistenteException("El aviso indicado no existe");
            // Validación de que el postulante ya haya postulado al aviso
            DetachedCriteria busqueda = DetachedCriteria.For<AvisoPostulante>();
            busqueda.Add(Restrictions.Eq("Aviso", avisoExistente));
            busqueda.Add(Restrictions.Eq("Postulante", postulanteExistente));
            ICollection<AvisoPostulante> postulaciones = AvisoPostulanteDAO.Listar(busqueda);
            if (postulaciones.Count > 0)
                throw new PostulacionDuplicadaException("El postulante ya postuló al aviso indicado");
            
            AvisoPostulante nuevaPostulacion = new AvisoPostulante();
            nuevaPostulacion.Aviso = avisoExistente;
            nuevaPostulacion.Postulante = postulanteExistente;
            nuevaPostulacion.FechaInscripcion = DateTime.Now;
            nuevaPostulacion.EsGanador = false;
            return AvisoPostulanteDAO.Crear(nuevaPostulacion);
        }

        public void seleccionarGanador(Int32 IdAviso, Int32 IdPostulante)
        {
            Aviso avisoExistente = AvisoDAO.Obtener(IdAviso);
            if (null == avisoExistente)
                throw new AvisoInexistenteException("El aviso indicado no existe");
            if (IdPostulante == 0)
                throw new Exception("El código de postulante no puede ser nulo o vacío");
            if (null == PostulanteDAO.Obtener(IdPostulante))
                throw new PostulanteInexistenteException("El postulante indicado no existe");
            DetachedCriteria busqueda = DetachedCriteria.For<AvisoPostulante>();
            busqueda.Add(Restrictions.Eq("Aviso", avisoExistente));
            busqueda.Add(Restrictions.Eq("EsGanador", true));
            ICollection<AvisoPostulante> postulaciones = AvisoPostulanteDAO.Listar(busqueda);
            if (postulaciones.Count > 0)
                throw new GanadorDuplicadoException("No se puede elegir a más de un ganador para el aviso");
            Postulante postulanteExistente = PostulanteDAO.Obtener(IdPostulante);
            DetachedCriteria busqueda2 = DetachedCriteria.For<AvisoPostulante>();
            busqueda2.Add(Restrictions.Eq("Aviso", avisoExistente));
            busqueda2.Add(Restrictions.Eq("Postulante", postulanteExistente));
            ICollection<AvisoPostulante> postulaciones2 = AvisoPostulanteDAO.Listar(busqueda2);
            if (postulaciones2.Count == 0)
                throw new Exception("El postulante indicado no puede ser ganador de un aviso al que no postuló");
            //Seleccionar ganador
            AvisoPostulante postulacionExistente = postulaciones2.First();
            postulacionExistente.EsGanador = true;
            AvisoPostulanteDAO.Modificar(postulacionExistente);

        }
    }
}

